﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Drawing;
using TKageyu.Utils;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
using System.ComponentModel;
using System.Data;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Media.Imaging;

namespace TiledShell.Models
{
    [Serializable()]
    public class Tile : ISerializable, INotifyPropertyChanged
    {
        private string _path;
        private int _numClicks;
        public string Path 
        { 
            get {return _path;}
            set
            {
                _path = value;
                NotifyProperyChanged("Path");
            }        
        }

        public int NumClicks
        {
            get { return _numClicks; }
            set
            {
                _numClicks = value;
                NotifyProperyChanged("NumClicks");
            }
        }
        public void LaunchApp()
        {
            NumClicks++;

            if (Path != "AddNew")
            {
                var procStartInfo = new System.Diagnostics.ProcessStartInfo(Path);
                var process = new System.Diagnostics.Process();
                process.StartInfo = procStartInfo;

                try
                {
                    process.Start();
                }
                catch (Exception e)
                {
                    //Swallow it.. I know it's bad.. :(
                }
            }
            else
            {
                string pathname = GetExe();
                if (pathname != null)
                {
                    var Tiles = TileListManager.Tiles;
                    Tile temp = new Tile(pathname);
                    Tiles.Insert(Tiles.Count-1, temp);
                }
            }
        }

        public void Delete()
        {
            var Tiles = TileListManager.Tiles;
            Tiles.Remove(this);
        }

        public BitmapImage GetIcon()
        //public System.Drawing.Image GetIcon()
        {
            if (Path != "AddNew")
            {
                try
                {

                    var iconExtractor = new IconExtractor(Path);
                    Icon[] icons = IconExtractor.SplitIcon(iconExtractor.GetIcon(0));

                    //var icon = FindIcon(icons, 128, 8);
                    var image = ExtractVistaIcon(iconExtractor.GetIcon(0));
                    var bmpImage = image.ToBitmapImage();
                    //var image = new BitmapImage();
                    //image.
                    return bmpImage;
                }

                catch
                {
                    Icon icon = Icon.ExtractAssociatedIcon(Path);
                    var image = icon.ToBitmapImage();
                    return image;
                }
            }
            else
            {
                //var icon = Icon.ExtractAssociatedIcon("../../Images/add.ico");
                //var image = icon.ToBitmapImage();
                Bitmap bmp = new Bitmap("../../Images/add.ico");
                BitmapImage image = bmp.ToBitmapImage();
                //var image = icon.ToBitmap();
                return image;
            }
        }

        public Tile(string _Path)
        {
            Path = _Path;
        }

        public Tile(SerializationInfo info, StreamingContext ctxt)
        {
            Path = (string)info.GetValue("Path", typeof(string));
            NumClicks = (int)info.GetValue("NumClicks", typeof(int));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Path", Path);
            info.AddValue("NumClicks", NumClicks);
        }
        public string GetExe()
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:\\" ;
            openFileDialog1.Filter = "exe files (*.exe)|*.exe" ;
            openFileDialog1.FilterIndex = 2 ;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                return openFileDialog1.FileName;
            }
            return null;
        }
        Icon FindIcon(Icon[] IconArray,int size, int bitDepth)
        {
            Icon matchingIcon = null;

            for (int i = 0; i < IconArray.Length; i++)
            {
                if (IconArray[i].Height == size && GetIconBitDepth(IconArray[i]) == bitDepth)
                    matchingIcon = IconArray[i];
            }

            return matchingIcon;
        }

        Bitmap ExtractVistaIcon(Icon icoIcon)
        {
            Bitmap bmpPngExtracted = null;
            try
            {
                byte[] srcBuf = null;
                using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
                { icoIcon.Save(stream); srcBuf = stream.ToArray(); }
                const int SizeICONDIR = 6;
                const int SizeICONDIRENTRY = 16;
                int iCount = BitConverter.ToInt16(srcBuf, 4);
                for (int iIndex = 0; iIndex < iCount; iIndex++)
                {
                    int iWidth = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex];
                    int iHeight = srcBuf[SizeICONDIR + SizeICONDIRENTRY * iIndex + 1];
                    int iBitCount = BitConverter.ToInt16(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 6);
                    if (iWidth == 0 && iHeight == 0 && iBitCount == 32)
                    {
                        int iImageSize = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 8);
                        int iImageOffset = BitConverter.ToInt32(srcBuf, SizeICONDIR + SizeICONDIRENTRY * iIndex + 12);
                        System.IO.MemoryStream destStream = new System.IO.MemoryStream();
                        System.IO.BinaryWriter writer = new System.IO.BinaryWriter(destStream);
                        writer.Write(srcBuf, iImageOffset, iImageSize);
                        destStream.Seek(0, System.IO.SeekOrigin.Begin);
                        bmpPngExtracted = new Bitmap(destStream); // This is PNG! :)
                        break;
                    }
                }
            }
            catch { return null; }
            return bmpPngExtracted;
        }

        private int GetIconBitDepth(Icon icon)
        {
            if (icon == null)
            {
                throw new ArgumentNullException("icon");
            }

            byte[] data = null;
            using (MemoryStream stream = new MemoryStream())
            {
                icon.Save(stream);
                data = stream.ToArray();
            }

            return BitConverter.ToInt16(data, 12);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyProperyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }
    }
}
